
package TCPTools;

import Type.AudioSound;
import Model.PathFile;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * La classe ServeurTCP cree un serveur en attente de 
 * connexion pour un transfert de fichier 
 *
 * @author      Frank Djomo
 * @author      Christelle SIAGO HAPPI
 * @author      djomopoueme@gmail.com
 * @author      christelle.siagohappi@gmail.com
 * @version     1.0
 */
public class ServeurTCP implements Runnable{
    
    
    private ServerSocket serverSocket ;
    private Socket       socket ;
    private BufferedReader  entree ; //lecture flux de la socket 
    private PrintWriter sortie ;     //Ecriture dans un fichier
    private boolean     isStart ;
    private int         port;
    private PathFile fileToReceived ;
    private long     sizeFileToReceived;
    private static File   defaultDirectory;
    private ProgressBar   barreDeProgression ;
     
    /**
    *  Cree un serveur TCP pour un transfert de fichier
    *  @param port     Port d'ecoute du serveur
    *  @param file     PathFile du fichier en cours de transfert
    *  @param taille   Taille du fichier en cours de transfert
    *  @see PathFile
    */
    public ServeurTCP(int port ,PathFile file,long taille)
    {      
        this.setPort(port);
        this.setFile(file);
        this.sizeFileToReceived =taille;
        this.setDefaultDirectory();
        barreDeProgression = new ProgressBar(taille, 'r');
        System.out.println("Lancement du serveur ...\n");
        try {
           //Etape 1 : Creation de la socket
            openServeur();
        } catch (IOException ex) {
        Logger.getLogger(ServeurTCP.class.getName()).log(Level.SEVERE, null, ex);
        }
        isStart=false;
    }

    private  void setPort(int port){
        if(port>1024) this.port=port;
    }
    private  void setFile(PathFile file){
        this.fileToReceived=new PathFile(file);
    }
    private boolean setDefaultDirectory()
    {
        defaultDirectory =new File("../ChatDownload");
        return defaultDirectory.mkdir();
    }
    /**
    *  Cree un repertoire pour le  fichiers transférés 
    *  @param defaultPath     Chemin du repertoire 
    */
    public static void  setDefaultDirectory(String defaultPath)
    {
        defaultDirectory =new File(defaultPath);
        defaultDirectory.mkdir();
    }
    /**
    *  Lance le serveur TCP pour un transfert de fichier
    *  Cette methode realise 4 opérations :
    * <ul>
    * <li> Attente de connexion d'un client 
    * <li> Ouverture des flux d'entrée et de sortie
    * <li> Reception des données 
    * <li> Fermeture des flux
    * </ul>
    */
    private void lancerServeur(){
        System.out.println("Serveur En attente de connexion\n");
        //Etape 2 : attente d'une connexion
        waitConnect();
        System.out.println("Connexion au serveur reussie ,Server >  : "+socket);

        //etape 3 : Recuperation des flux de la connexion
        openFlux();
        try {
        //etape 4 : Traiter la connexion .
        receptionData();
        } catch (IOException ex) {
        Logger.getLogger(ServeurTCP.class.getName()).log(Level.SEVERE, null, ex);
        }
        //Etape ( : Fermer les flux 
        closeFlux();
    }
    /**
    * Création du ServeurSocket
    * @throws IOException
    */
    private void openServeur() throws IOException
    {
        try{
            //Creation de la socket serveur
            serverSocket = new ServerSocket(port);
        }catch (java.io.IOException ex){
            Logger.getLogger(ServeurTCP.class.getName()).log(Level.SEVERE, null, ex);
            serverSocket.close();
        }
    }

    /**
    * Attente de connexion
    */
    private void  waitConnect()
    {
        try{
            //recuperation de la socket
            socket = serverSocket.accept();
        }
        catch(java.io.IOException ex){
            try {
                Logger.getLogger(ServeurTCP.class.getName()).log(Level.SEVERE, null, ex);
                socket.close();
            } catch (IOException ex1) {
                Logger.getLogger(ServeurTCP.class.getName()).log(Level.SEVERE, null, ex1);
            }
        }
        isStart=true;
    }
    /**
    * Ouverture des flux d'entrée et sortie
    */
    private void openFlux()
    {
        try{
             //Recuperation des flux
            entree       = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            sortie = new PrintWriter(new FileWriter( 
                  new File(defaultDirectory+"/"+fileToReceived.getName())),true
                 );

        }catch (java.io.IOException ex){
            try {
                Logger.getLogger(ServeurTCP.class.getName()).log(Level.SEVERE, null, ex);
                entree.close();
                sortie.close();
            } catch (IOException ex1) {
                Logger.getLogger(ServeurTCP.class.getName()).log(Level.SEVERE, null, ex1);
            }
        }
    }

    /**
    * Reception des données
    * @throws IOException
    */
    private void receptionData() throws IOException{

        int size = (int)sizeFileToReceived;

        Vitesse vitesseTransfert = new Vitesse();

        int octectLu=0;
        int octectTraite = 0;
        char[]   recu = new char[size]; // Création d'un nouveau tableau

        System.out.println("Debut de la transmission");
        boolean transfert =true ;

        long timeDebut =new Date().getTime();	    
        // Tant que l'on ne reçoit pas tout le fichier             
        while(transfert) 
        {
              octectLu= entree.read(recu,octectTraite, size-octectTraite);
              System.out.println("Reception data : "+recu.toString());

              if(octectLu>0) // Si on a lu des données
              {
                    sortie.write(recu);
                    sortie.flush();
               }
              octectTraite = octectTraite + octectLu;
              // Calcul de la vitesse de transfert
              vitesseTransfert.getVitesse(timeDebut,octectTraite);
              barreDeProgression.setProgressBar(vitesseTransfert);
               if(octectTraite == size){
                   transfert = false;
                   System.out.println("Fin de la transmission");
                   barreDeProgression.setEtat("Sauvegardé dans "+defaultDirectory+"\\"+fileToReceived.getName());
                   AudioSound msg= new AudioSound(getClass().getResource("/Ressources/sons/transfert.wav"));
                   new Thread(msg).start();
                }
        }        
    }

    /**
    * Fermeture les flux
    */
    private void closeFlux()
    {
        try{
            if( entree!=null )
                entree.close();      // Fermeture du flux d'entrée
            if( sortie!=null )
                sortie.close();     // Fermeture du flux de sortie
            if( socket!=null)
                socket.close();     // Fermeture du socket
            if( serverSocket!=null )
                serverSocket.close();         // Fermeture du serveur
        }catch (java.io.IOException ex){
            Logger.getLogger(ServeurTCP.class.getName()).log(Level.SEVERE, null, ex);
        }
         System.out.println("Fermeture des flux serveur");
    }

    /**
    * Lance le serveur TCP pour un transfert de fichier.
    * Cette methode realise 4 opérations :
    * <ul>
    * <li> Attente de connexion d'un client 
    * <li> Ouverture des flux d'entrée et de sortie
    * <li> Reception des données 
    * <li> Fermeture des flux
    * </ul>
    */
    @Override
    public void run() {
        //throw new UnsupportedOperationException("Not supported yet.");    
        lancerServeur();
    }
}
